/****************************************************************
 **  Nombre: DAOProgramaEducativo.java                          *
 **  Version: 1.0.0                                             *
 **  Diagrama: GAPI v2.3.1                                      *
 **  Autor: Amado de Jesús Canté Cauich                         *
 **  Creado: 12-feb-2013 
 *   Caso de uso: MGOA1,2,3,4,5
 **  Modificado: 17/03/2013 (Alonso Orozco)                                    *
 ***************************************************************/
package DAO;

import AccesoBD.AccesoBaseDatos;
import Dominio.AsignaturaOptativa;
import Dominio.Carrera;
import Dominio.ProgramaEducativo;
import Dominio.ReticulaAcademica;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Clase que controla el acceso a la base de datos de programas educativos. 
 */
public class DAOProgramaEducativo {
    public static final String TABLA_PROGRAMAS_EDUCATIVOS = "programas_educativos";
    public static final String COLUMNA_NOMBRE = "nombre";
    public static final String COLUMNA_CVE_CARRERA = "clave_carrera";
    public static final String COLUMNA_CVE_RETICULA = "clave_ret_acad";
    public static final String COLUMNA_CVE_PROGRAMA = "clave_programa_educativo";
    private DAOAsignaturaOptativa daoAsignaturaOptativa;
    private DAOReticulaAcademica daoReticula;
    private AccesoBaseDatos acceso = new AccesoBaseDatos();
    private Connection conexion = null;
    /**
     * Constructor de la clase
     */
    public DAOProgramaEducativo(){
        this.conexion = this.acceso.abrirConexion();
        this.daoAsignaturaOptativa = new DAOAsignaturaOptativa();
        this.daoReticula = new DAOReticulaAcademica();
    }
    /**
     * Registra un programa educativo
     * @param programa Objeto programa educativo
     * @return True si es correcto el registro de lo contrario regresa false
     */
    public boolean registrarProgramaEducativo(ProgramaEducativo programa){
        boolean ok = true;
        try{
            ReticulaAcademica reticula;
            ProgramaEducativo p;
            ArrayList<AsignaturaOptativa> optativas = programa.getReticula().getAsignaturasOptativas();
            Carrera carrera = programa.getCarrera();
            reticula = daoReticula.registrarReticulaAcademica(programa.getReticula());
            if(reticula != null){
                String queryRegistro = "INSERT INTO "+TABLA_PROGRAMAS_EDUCATIVOS+" ("
                        +COLUMNA_NOMBRE+","+ COLUMNA_CVE_CARRERA+","+COLUMNA_CVE_RETICULA+") VALUES('"
                        +programa.getNombre().toUpperCase()+"','"+carrera.getClaveCarrera()+"','"+reticula.getClaveReticulaAcademica()+ "')";
                PreparedStatement sentencia = this.conexion.prepareStatement(queryRegistro,Statement.RETURN_GENERATED_KEYS);
                int afectados = sentencia.executeUpdate();
                if(afectados == 0){
                    ok = false;
                    throw new SQLException("Problema registrando el programa educativo.");
                }else{
                    ResultSet generado = sentencia.getGeneratedKeys();
                    if(generado.next()){
                        p = new ProgramaEducativo(programa.getNombre().toUpperCase(),generado.getInt(1),programa.getCarrera(),reticula);
                        for(int k=0;k<p.getReticula().getAsignaturasOptativas().size();k++){
                            AsignaturaOptativa o = p.getReticula().getAsignaturasOptativas().get(k);
                            o.setProgramaEducativo(p);
                        }
                        daoAsignaturaOptativa.registrarOptativas(p);
                    }else{
                        ok = false;
                        throw new SQLException();
                    }
                }
            }else{
                ok = false;
                throw new SQLException();
            }
        }catch(SQLException ex){
            System.out.println("Ocurrió un problema al intentar registrar el programa.\n");
            ex.printStackTrace();
        }
        return ok;
    }
    /**
     * Elimina un programa educativo.
     * @param clavePE La clave del programa educativo en la base de datos
     */
    public void eliminarProgramaEducativo(int clavePE){
        try {
            Statement sentencia = acceso.crearSentenciaBD(conexion);
            String query = "DELETE FROM "+TABLA_PROGRAMAS_EDUCATIVOS+" WHERE "+COLUMNA_CVE_PROGRAMA +"='"+clavePE+"'";
            ProgramaEducativo p = this.buscarPrograma(clavePE);
            sentencia.executeUpdate(query);
            DAOReticulaAcademica daoreticula = new DAOReticulaAcademica();
            daoreticula.eliminarReticula(p.getReticula().getClaveReticulaAcademica(),clavePE);
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /**
     * Obtiene la clave de la reticula academica.
     * @param nombrePE Nombre del prograba educativo
     * @return La clave de la reticula academica
     */
    public int obtenerClaveReticulaAcademica(String nombrePE){
        int claveRA = 0;
        try {          
            ResultSet resultado = null;
             Statement sentencia = acceso.crearSentenciaBD(conexion);
             String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS + " WHERE nombre = '" + nombrePE + "' ";
                resultado = sentencia.executeQuery(query);
                if(resultado.next()){
                claveRA = resultado.getInt(4);
                }
           
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
         return claveRA;
    }
    /**
     * Obtiene la clave del programa educativo.
     * @param nombrePE El nombre del programa educativo.
     * @return La clave del programa educativo.
     */
     public int obtenerClavePE(String nombrePE){
        int clavePE = 0;
        try {          
            ResultSet resultado = null;
             Statement sentencia = acceso.crearSentenciaBD(conexion);
             String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS + " WHERE nombre = '" + nombrePE + "' ";
                resultado = sentencia.executeQuery(query);
                while(resultado.next()){
                clavePE = resultado.getInt(1);
                }
           
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
         return clavePE;
    }
    /**
     * Lista los programas educativos.
     * @return Arreglo con los objetos de programas educativos.
     */
    public ArrayList<ProgramaEducativo> listarProgramas(){
        ArrayList<ProgramaEducativo> programas = new ArrayList<ProgramaEducativo>();
        ResultSet resultado = null;
        DAOCarrera daocarrera = new DAOCarrera();
        DAOReticulaAcademica daoreticula = new DAOReticulaAcademica();        
        try {            
            Statement sentencia = acceso.crearSentenciaBD(conexion);
            String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS;
            resultado = sentencia.executeQuery(query);
            while(resultado.next()){
                int clavePrograma = resultado.getInt(1);
                String nombre = resultado.getObject(2).toString();
                int claveCarrera = resultado.getInt(3);
                int claveReticula = resultado.getInt(4);
                Carrera carrera = daocarrera.buscarCarrera(claveCarrera);
                ReticulaAcademica reticula = daoreticula.obtenerReticula(claveReticula, clavePrograma);
                ProgramaEducativo programa = new ProgramaEducativo(nombre, clavePrograma, carrera, reticula);
                programas.add(programa);
            }
            return programas;
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
        return programas;
    }
    /**
     * Busca un programa educativo.
     * @param clavePrograma Clave del programa educativo.
     * @return El objeto del programa educativo.
     */
    public ProgramaEducativo buscarPrograma(int clavePrograma){
        DAOCarrera daoCarrera = new DAOCarrera();
        try{
            Statement sentencia = acceso.crearSentenciaBD(conexion);
            String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS+" WHERE "+COLUMNA_CVE_PROGRAMA+"='"+clavePrograma+"';";
            ResultSet resultado = sentencia.executeQuery(query);
            ProgramaEducativo programa;
            if(resultado.next()){
                resultado.first();
                int cvePrograma = resultado.getInt(1);
                String nombre = resultado.getString(2);
                int cveCarrera = resultado.getInt(3);
                int cveReticula = resultado.getInt(4);
                ReticulaAcademica reticula = daoReticula.obtenerReticula(cveReticula, clavePrograma);
                Carrera carrera = daoCarrera.buscarCarrera(cveCarrera);
                programa = new ProgramaEducativo(nombre, cvePrograma, carrera, reticula);
                return programa;
            }
        }catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    /**
     * Lista los programas educativos editables
     * @return El arreglo con los programas educativos editables.
     */
    public ArrayList<ProgramaEducativo> listarProgramasEditables(){
        ArrayList<ProgramaEducativo> programas = new ArrayList<>();
        try{
           Statement sentencia = this.acceso.crearSentenciaBD(conexion);
           String query = "SELECT "+COLUMNA_CVE_PROGRAMA+" FROM "
                   +TABLA_PROGRAMAS_EDUCATIVOS+" WHERE "
                   +TABLA_PROGRAMAS_EDUCATIVOS+"."+COLUMNA_CVE_PROGRAMA+" NOT IN("
                   +"SELECT clave_PE FROM rel_alumno_pe);";
           ResultSet resultado = sentencia.executeQuery(query);
           while(resultado.next()){
               int clavePrograma = resultado.getInt(1);
               ProgramaEducativo p = this.buscarPrograma(clavePrograma);
               if(p!=null){
                   programas.add(p);
               }
           }
           Statement nombrePE = this.acceso.crearSentenciaBD(conexion);
           String queryNombres="SELECT programaEducativo FROM AsignaturasOferta";
           ResultSet nombresPE = nombrePE.executeQuery(queryNombres);
           boolean continuar;
           while(nombresPE.next()){
               continuar = true;
               for(int i=0;i<programas.size() && continuar;i++){
                   if(programas.get(i).getNombre().equalsIgnoreCase(nombresPE.getString(1))){
                       programas.remove(i);
                       continuar = false;
                   }
               }
           }
           return programas;
        }catch(SQLException ex){
            return programas;
        }
    }
    /**
     * Cierra la conexion con la base de datos.
     */
    public void cerrarconexionAProgramas(){
        acceso.cerrarConexion(conexion);
    }
    /**
     * Edita el nombre del prograba educativo
     * @param clvePrograma Clave del programa educativo a editar
     * @param nombre El nuevo nombre del programa educativo
     * @return True si se pudo actualizar y false en caso contrario.
     */
    public boolean editarNombrePrograma(int clvePrograma, String nombre){
        try{
            Statement sentencia = this.acceso.crearSentenciaBD(conexion);
            String query = "UPDATE "+TABLA_PROGRAMAS_EDUCATIVOS+" SET "
                    +COLUMNA_NOMBRE+"='"+nombre+"' WHERE "+COLUMNA_CVE_PROGRAMA
                    +"='"+clvePrograma+"';";
            int afectado = sentencia.executeUpdate(query);
            return (afectado>0);
        }catch(SQLException ex){
            return false;
        }
    }
    /**
     * Edita la carrera del programa educativo.
     * @param clavePrograma Clave del programa educativo
     * @param claveCarrera Claved e la carrera del programa educativo.
     * @return True si se pudo editar, false de lo contrario.
     */
    public boolean editarCarreraPrograma(int clavePrograma, int claveCarrera){
        try{
            Statement sentencia = this.acceso.crearSentenciaBD(conexion);
            String query = "UPDATE "+TABLA_PROGRAMAS_EDUCATIVOS+" SET "
                    +COLUMNA_CVE_CARRERA+"='"+claveCarrera+"' WHERE "+COLUMNA_CVE_PROGRAMA
                    +"='"+clavePrograma+"';";
            int afectado = sentencia.executeUpdate(query);
            return (afectado>0);
        }catch(SQLException ex){
            return false;
        }
    }
    
    /**
     * Actualiza la retícula asociada al programa educativo.
     * @param clavePrograma Clave del programa educativo.
     * @param reticula Instancia de la nueva retícula académica del programa educativo.
     * @return True si se realizó correctamente la actualización, False en caso contrario.
     */
     public boolean actualizaReticulaAsociada(int clavePrograma, ReticulaAcademica reticula){
        int claveRetAnterior = this.obtenerClaveReticulaAcademica(this.buscarPrograma(clavePrograma).getNombre());
        DAOReticulaAcademica daoretacad = new DAOReticulaAcademica();
        ProgramaEducativo p = this.buscarPrograma(clavePrograma);
        ReticulaAcademica nuevaReticula = daoretacad.registrarReticulaAcademica(reticula);
        ArrayList<AsignaturaOptativa> optativas = reticula.getAsignaturasOptativas();
        for(int i=0;i<optativas.size();i++){
            optativas.get(i).setProgramaEducativo(p);
        }
        DAOAsignaturaOptativa daoptativas = new DAOAsignaturaOptativa();
        boolean ok = daoptativas.actualizaOptativasPE(optativas,clavePrograma);
        if(nuevaReticula!=null && ok){
            try{
                Statement sentencia = acceso.crearSentenciaBD(conexion);
                String query = "UPDATE "+TABLA_PROGRAMAS_EDUCATIVOS+" SET "
                        +COLUMNA_CVE_RETICULA+"='"+nuevaReticula.getClaveReticulaAcademica()
                        +"' WHERE "+COLUMNA_CVE_PROGRAMA+"='"+clavePrograma+"';";
                int afectado = sentencia.executeUpdate(query);
                if(afectado>0){
                    boolean sigue = daoretacad.eliminarReticula(claveRetAnterior, clavePrograma);
                    return sigue;
                }else{
                    return false;
                }
            }catch(SQLException ex){
                return false;
            }
        }else{
            return false;
        }
    }
     /**
      * Obtiene la abreviatura del programa educativo
      * @param clavePE Clave del programa educativo segun la base de datos
      * @return El nombre o abreviatura del programa educativo.
      */
    public String obtenerabreviaturaDePE(int clavePE) {
        String abreviaturaPE = "";
        try {
            String queryBusqueda = "SELECT "+COLUMNA_NOMBRE+" FROM "+TABLA_PROGRAMAS_EDUCATIVOS+" WHERE "+COLUMNA_CVE_PROGRAMA+" = '"+clavePE+"';";

            Statement sentencia = acceso.crearSentenciaBD(conexion);
            ResultSet resultado = sentencia.executeQuery(queryBusqueda);

            while(resultado.next()){
            abreviaturaPE = resultado.getString(1);
            }
        } catch (SQLException ex) {
        Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }

            return abreviaturaPE;
        }
        
    /**
     * Verifica la existencia de un programa educativo con el nombre indicado en la base de datos.
     * @param nombreDelProgramaEducativo Nombre del programa ecucativo que se desea verificar si existe.
     * @return True si existe un programa educativo con el nombre indicado, False en caso contrario.
     */
     public boolean existeProgramaEducativo(String nombreDelProgramaEducativo) {
         
         boolean existe = false;
         
         try {          
            ResultSet resultado = null;
             Statement sentencia = acceso.crearSentenciaBD(conexion);
             String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS + " WHERE nombre = '" + nombreDelProgramaEducativo + "' ";
            resultado = sentencia.executeQuery(query);
                            
            while(resultado.next()){
                existe = true;
            }
           
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
         
         
        return existe;
     }    
     /**
      * Verifica si el programa educativo es editable
      * @param nombreDelProgramaEducativo Nombre del programa educativo
      * @param claveProgramaEducativo Clave del programa educativo
      * @return True si existe, false en caso contrario.
      */
     public boolean esEditableElProgramaEducativo(String nombreDelProgramaEducativo, int claveProgramaEducativo) {
         
         boolean editable = true;
         
         try {          
            ResultSet resultado = null;
             Statement sentencia = acceso.crearSentenciaBD(conexion);
             String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS + " WHERE nombre = '" + nombreDelProgramaEducativo + "' AND "+COLUMNA_CVE_PROGRAMA+" <> '"+claveProgramaEducativo+"';";
            resultado = sentencia.executeQuery(query);
                            
            while(resultado.next()){
                editable = false;
            }
           
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
         
         
        return editable;
     }     
     /**
      * Verifica si existe el programa educativo con una carrera
      * @param claveCarrera Clave de la carrera
      * @return True si existe, false en caso contrario
      */
     public boolean existeProgramaEducativoConCarrera(int claveCarrera) {
         
         boolean existe = false;
         
         try {          
            ResultSet resultado = null;
             Statement sentencia = acceso.crearSentenciaBD(conexion);
             String query = "SELECT * FROM "+TABLA_PROGRAMAS_EDUCATIVOS + " WHERE "+COLUMNA_CVE_CARRERA+" = '" + claveCarrera + "' ";
            resultado = sentencia.executeQuery(query);
                            
            while(resultado.next()){
                existe = true;
            }
           
        } catch (SQLException ex) {
            Logger.getLogger(DAOProgramaEducativo.class.getName()).log(Level.SEVERE, null, ex);
        }
         
         
        return existe;
     }
}
